home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 32 / Mac Magazin and MacEasy Magazine CD - Issue 32.iso / Grafik & Text / OzTeX3.0 / MetaPost / Inputs / format.mp < prev    next >
Text File  |  1996-08-24  |  7KB  |  235 lines

  1. % Macros for generating typeset pictures of computed numbers
  2.  
  3. % format(f,x)               typeset generalized number x using format string f
  4. % Mformat(f,x)              like format, but x is in Mlog form (see marith.mp)
  5. % init_numbers(s,m,x,sn,e)  choose typeset style given sample sign, mantissa,...
  6. % roundd(x,d)               round numeric x to d places right of decimal point
  7. % Fe_base                   what precedes the exponent for typeset powers of 10
  8. % Fe_plus                   plus sign if any for typesetting positive exponents
  9. % Ten_to[]                  powers of ten for indices 0,1,2,3,4
  10.  
  11. % Other than the above-documented user interface, all externally visible names
  12. % start with F and end with _.
  13.  
  14.  
  15. if unknown Fmfont_:                     % If this file has not been read yet
  16. begingroup interim warningcheck:=0;     % Allow big numbers in token lists
  17.  
  18. input string
  19.  
  20.  
  21. %%%%%%%%%%%%%%%%%%%%%%% Choosing the Layout %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  22.  
  23. picture Fmneg_, Femarker_, Feneg_, Fe_base, Fe_plus;
  24. string Fmfont_, Fefont_;
  25. numeric Fmscale_, Fescale_, Feraise_;
  26.  
  27.  
  28. % Argument s is a leading minus sign;  m is a 1-digit mantissa;
  29. % x is whatever follows the mantissa; sn is a leading minus for the exponent;
  30. % and e is a 1-digit exponent.  Numbers in scientific notation are constructed
  31. % by placing these peices side-by-side; decimal numbers use only m and/or s.
  32. % To get exponenets with leading plus signs, assign to Fe_plus after calling
  33. % init_numbers.  To do something special with a unit mantissa followed by x,
  34. % assign to Fe_base after calling init_numbers.
  35. vardef init_numbers(expr s, m, x, sn, e) =
  36.   Fmneg_ := s;
  37.   for p within m: 
  38.     Fmfont_ := fontpart p;
  39.     Fmscale_ := xxpart p;
  40.     exitif true;
  41.   endfor
  42.   Femarker_ := x;
  43.   Feneg_ := sn;
  44.   for p within e:
  45.     Fefont_ := fontpart p;
  46.     Fescale_ := xxpart p;
  47.     Feraise_ := ypart llcorner p;
  48.     exitif true;
  49.   endfor
  50.   Fe_base := Fline_up_("1" infont Fmfont_ scaled Fmscale_, Femarker_);
  51.   Fe_plus := nullpicture;
  52. enddef;
  53.  
  54.  
  55.  
  56. %%%%%%%%%%%%%%%%%%%%%%% Low-Level Typesetting %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  57.  
  58. vardef Fmant_(expr x) =
  59.   (decimal abs x infont Fmfont_ scaled Fmscale_)
  60. enddef;
  61.  
  62. vardef Fexp_(expr x) =
  63.   (decimal x infont Fefont_ scaled Fescale_ shifted (0,Feraise_))
  64. enddef;
  65.  
  66. vardef Fline_up_(text t_) =
  67.   save p_, c_;
  68.   picture p_; p_=nullpicture;
  69.   pair c_; c_=(0,0);
  70.   for q_=t_:
  71.     addto p_ also q_ if string q_: infont defaultfont scaled defaultscale fi
  72.         shifted c_;
  73.     c_ := (xpart lrcorner p_, 0);
  74.   endfor
  75.   p_
  76. enddef;
  77.  
  78. vardef Fdec_o_(expr x) =
  79.   if x<0: Fline_up_(Fmneg_, Fmant_(x))
  80.   else: Fmant_(x)
  81.   fi
  82. enddef;
  83.  
  84. vardef Fsci_o_(expr x, e) =
  85.   Fline_up_(if x<0: Fmneg_,fi
  86.       if abs x =1:  Fe_base  else:  Fmant_(x), Femarker_  fi,
  87.       if e<0:  Feneg_  else:  Fe_plus  fi,
  88.       Fexp_(abs e))
  89. enddef;
  90.  
  91.  
  92. % Assume prologues=1 implies troff mode.  TeX users who what prologues on
  93. % should use some other positive value.  The mpx file mechanism requires
  94. % separate input files here.
  95. if prologues=1:  input troffnum
  96. else:  input texnum
  97. fi
  98.  
  99.  
  100.  
  101. %%%%%%%%%%%%%%%%%%%%%%% Scaling and Rounding %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  102.  
  103. % Find a pair p where x=xpart p*10**ypart p and either p=(0,0) or xpart p is
  104. % between 1000 and 9999.99999.  This is the `exponent form' of x.
  105. vardef Feform_(expr x) =
  106.   interim warningcheck:=0;
  107.   if string x:
  108.     if unknown Mzero: scantokens "input marith"; fi
  109.     Meform(Mlog_str x)
  110.   else:
  111.     save b, e;
  112.     b=x; e=0;
  113.     if abs b>=10000: (b/10, 1)
  114.     elseif b=0: origin
  115.     else: forever:
  116.       exitif abs b>=1000;
  117.       b:=b*10; e:=e-1;
  118.       endfor
  119.      (b, e)
  120.     fi
  121.   fi
  122. enddef;
  123.  
  124. % The marith.mp macros include a similar macro Meform that converts from
  125. % `Mlog form' to exponent form.
  126.  
  127.  
  128. % In case rounding has made the xpart of an exponent form number too large,
  129. % fix it.
  130. vardef Feadj_(expr x, y) =
  131.   if abs x>=10000: (x/10, y+1)   else: (x,y)  fi
  132. enddef;
  133.  
  134.  
  135. % Round x to d places right of the decimal point.  When d<0, round to the
  136. % nearest multiple of 10 to the -d.
  137. vardef roundd(expr x, d) =
  138.   if abs d >4:
  139.     if d>0: x else: 0 fi
  140.   elseif d>0:
  141.     save i; i=floor x;
  142.     i + round(Ten_to[d]*(x-i))/Ten_to[d]
  143.   else:
  144.     round(x/Ten_to[-d])*Ten_to[-d]
  145.   fi
  146. enddef;
  147.  
  148. Ten_to0=1; Ten_to1=10; Ten_to2=100; Ten_to3=1000; Ten_to4=10000;
  149.  
  150.  
  151.  
  152. % Round an exponent form number p to k significant figures.
  153. primarydef p Fprec_ k =
  154.   Feadj_ (roundd(xpart p,k-4), ypart p)  enddef;
  155.  
  156. % Round an exponent form number p to k digits right of the decimal point.
  157. primarydef p Fdigs_ k =
  158.   Feadj_ (roundd(xpart p,k+ypart p), ypart p)  enddef;
  159.  
  160.  
  161.  
  162. %%%%%%%%%%%%%%%%%%%%%%% High-Level Routines %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  163.  
  164. % The following operators convert z from exponent form and produce typeset
  165. % output:  Formsci_ generates scientific notation; Formdec_ generates decimal
  166. % notation; and Formgen_ generates whatever is likely to be most compact.
  167.  
  168. vardef Formsci_(expr z) = Fsci_o_(xpart z/1000, ypart z +3)  enddef;
  169.  
  170. vardef Formdec_(expr z) =
  171.   if ypart z>0: Formsci_(z)
  172.   else:
  173.     Fdec_o_(xpart z
  174.         if ypart z>=-4: /Ten_to[-ypart z]
  175.     else: for i=ypart z upto -5: /(10) endfor/10000  fi)
  176.   fi
  177. enddef;
  178.  
  179. vardef Formgen_(expr q) =
  180.   clearxy; (x,y)=q;
  181.   if x=0: Formdec_
  182.   elseif y>=-6: Formdec_
  183.   else: Formsci_
  184.   fi (q)
  185. enddef;
  186.  
  187.  
  188. def Fset_item_(expr s) =
  189.   if s<>"":  s infont defaultfont scaled defaultscale,  fi
  190. enddef;
  191.  
  192.  
  193. % For each format letter, the table below tells how to round and typeset
  194. % a quantity z in exponent form.
  195. string fmt_[];
  196. fmt_[ASCII "e"] = "Formsci_(z Fprec_ p)"; % scientific, p significant figures
  197. fmt_[ASCII "f"] = "Formdec_(z Fdigs_ p)"; % decimal, p digits right of the point
  198. fmt_[ASCII "g"] = "Formgen_(z Fprec_ p)"; % decimal or scientific, p sig. figs.
  199. fmt_[ASCII "G"] = "Formgen_(z Fdigs_ p)"; % decimal or scientific, p digits
  200.  
  201.  
  202. % The format and Mformat macros take a format string f and generate typeset
  203. % output for a numeric quantity x.  String f should contain a `%' followed by
  204. % an optional number and one of the format letters defined above.  The number
  205. % should be an integer giving the precision (default 3).  
  206.  
  207. vardef dofmt_@#(expr f, x) =
  208.   if f="": nullpicture
  209.   else:
  210.     interim warningcheck:=0;
  211.     save k, l, s, p, z;
  212.     pair z; z=@#(x);
  213.     k = 1 + cspan(f, "%"<>);
  214.     l-k = cspan(substring(k,infinity)of f, isdigit);
  215.     p = if l>k:  scantokens substring(k,l)of f  else: 3 fi;
  216.     string s; s=fmt_[ASCII substring (l,l+1) of f];
  217.     if unknown s:
  218.       if k<=length f: errmessage("No valid format letter found in "&f); fi
  219.       s = "nullpicture";
  220.     fi
  221.     Fline_up_(
  222.       Fset_item_(substring (0,k-1) of f)
  223.       scantokens s,
  224.       Fset_item_(substring (l+1,infinity) of f)
  225.       nullpicture)
  226.   fi
  227. enddef;
  228.  
  229. vardef format(expr f, x) = dofmt_.Feform_(f,x) enddef;
  230. vardef Mformat(expr f, x) = dofmt_.Meform(f,x) enddef;
  231.  
  232.  
  233. endgroup;    % restore warningcheck to previous value
  234. fi           % end the if..fi that encloses this file
  235.